Aus MADS direkt in ein ATR assemblieren

← Zurück zum Forum

Im AtariAge Forum kam die Tage die Frage auf, wie man direkt in ein Disk Image assemblieren kann. Ich hatte das vor drei Monaten mal gemacht um das FujiNet NOS anzupassen und den Code jetzt mit einem Beispiel zusammengepackt.

Vielleicht kann es ja jemand hier gebrauchen.

Wie schon geschrieben, ist der Code für MADS, sollte aber für jeden Assembler anpassbar sein, dem man das Erzeugen von XEX-Headern abgewöhnen kann und der sinnvoll rechnen kann (Integer Division und Modulo). Die von MADS erstellte Datei heißt immer .XEX und muss noch in .ATR umbenannt werden. (Vielleicht kennt jemand eine Direktive, die beliebige Extensions zulässt.) Da der Atari Bootvorgang nur ein Byte für die Sektorzahl vorsieht (1-255) und davon noch sechs Byte für den Bootheader abgehen, verbleiben maximal 32634 Bytes für euch.

Die Geschichte hat auch ein paar Randbedingungen, die vermutlich analog zu denen sind, die beim Bau von ROMs auch gelten:

  • Euer Code muss an einem Stück sein weil der Bootlader alle Sektoren in einen zusammenhängenden Speicherbereich lädt. Ihr könnt also kein "ORG" oder "=+x" innerhalb des zu ladenden Programmcodes verwenden.
  • Aus demselben Grund dürft ihr keine Speicherbereiche nur definieren, sondern müsst sie mit einem (ggf. Dummy) Wert initialisieren. ".DS 10" geht z.B. nicht. Ihr müsst dafür ":10 .BYTE $00" verwenden, weil dann die entsprechende Anzahl an $00-Bytes eingefügt wird, anstatt nur den Programmzähler hochzuzählen.
  • Wenn das OS den Bootcode geladen hat, macht es zwingend einen JSR zum 7. Byte des geladenen Codes. Wenn euer Programm dort keinen Init-Code hat, müsst ihr dort entweder einen JMP zu eurem Init-Code einbauen oder ein RTS falls ihr gar keinen Init-Code habt. (Siehe auskommentierte Zeilen in meiner Source.)

Anmerkung zu 1. und 2.: Wenn zusätzlicher Speicher erst zur Laufzeit befüllt wird, kann dieser durchaus mit weiteren ORGs und .DS definiert werden, nur muss das außerhalb des geladenen Bereichs passieren. In meinem Beispiel habe ich einen Block hinter EODISK eingefügt um den veränderten Zeichensatz abzulegen. Es sollte auch direkt am Anfang vor "meinem" ORG möglich sein. Dann müsst ihr zusätzlich das "OPT h-" so verschieben, dass es direkt hinter dem ersten ORG steht. (Getestet habe ich das aber nicht.)

CODEST  EQU $4000   ; start of program code

; Start of code minus size of boot-header minus size of ATR-header
    ORG CODEST-6-16

; directive to only create code and not create any XEX-headers
    OPT h-

; ATR Header for SD disk 90K
    DTA $96,$02,$80,$16,$80
:11 DTA $00


; boot header
HDR .BYTE   $00         ; BFLAG: Boot flag equals zero (unused)
    .BYTE   [BOOTEND+127-HDR]/128   ; BRCNT: Number of consecutive sectors to read
    .WORD   HDR         ; BLDADR: Boot sector load address ($3FFA)
    .WORD   RUN         ; RUN address (called after RTS from INIT)


; The OS will unconditionally JSR to here after the boot process

INIT:
; Uncomment in case you do not have any initialization code
;   RTS

; Uncomment in case your initialization code is not right at the beginning
;   JMP myINIT

; CODEST: points to here

; START of example program - REPLACE with your code
    LDX $2f4
    INX
    STX $cc
    LDY #0
    STY $cb
chloop  LDA ($cb),y
    STA chset+$100,y
    INY
    BNE chloop

    LDY #7
aloop   LDA tree,y
    STA chset+$108,y
    DEY
    BPL aloop

    LDA #>chset
    STA $2f4

    LDA #<dlist
    STA $230
    LDA #>dlist
    STA $231

    RTS

tree    .BYTE   %00000000
    .BYTE   %00001000
    .BYTE   %00011100
    .BYTE   %00111110
    .BYTE   %01111111
    .BYTE   %00001000
    .BYTE   %00001000
    .BYTE   %00000000

dlist   .BYTE   $70,$70,$70,$70,$70
    .BYTE   $47
    .WORD   screen
    .BYTE   $41
    .WORD   dlist

screen  .BYTE   "     MERRY XMAS     "


; The OS will JMP to here after the RTS from INIT above

RUN:
    LDX #0
dlloop  STX $d40a
    STX $d016
    DEX
    JMP dlloop

; END of example program  - REPLACED by your code

BOOTEND:

PGEND   = *

; =================================================================
; VTOC and Directory
;

; $10 is the added ATR-header
:($B390-*+HDR-$10) DTA $00
VTOCSTA:
    DTA $02,$BD,$02
VTOCEND:

; Fill the remaining bytes of the VTOC sector
    :($80+VTOCSTA-VTOCEND) DTA $00

DIRSTA:
    DTA $60,$00,$00,$00,$00,C"***********"
    DTA $60,$00,$00,$00,$00,C"This text  "
    DTA $60,$00,$00,$00,$00,C"will show  "
    DTA $60,$00,$00,$00,$00,C"up as DOS 2"
    DTA $60,$00,$00,$00,$00,C"directory. "
    DTA $60,$00,$00,$00,$00,C"   ----    "
    DTA $60,$00,$00,$00,$00,C"maximum    "
    DTA $60,$00,$00,$00,$00,C"64 lines   "
    DTA $60,$00,$00,$00,$00,C"***********"
    DTA $C0
DIREND:

; Fill the remaining sectors of the directory
    :($400+DIRSTA-DIREND) DTA $00

; Sectors behind directory
    :($80*352) DTA $00

EODISK:
; END of disk image


; from here on NO MORE data but only definitions, if needed

    ORG $1000
chset   .DS $200

    END
Anhänge:

Soll hier eine Bootdiskette btw. ein Bootloader assembliert oder eine XEX auf eine DOS-Diskette geschrieben werden? Für letzteres würde ich ein Makefile verwenden.

http://fujiama.eu https://abbuc.de/~atarixle/ BOSS-X - das Finale: https://abbuc.de/~atarixle/?article=bossxfinaleditionprerelease

Ersteres. Ich hatte mir das gebastelt, als ich mit WUDSN am FujiNet NOS rumgebastelt habe, um SynCalc damit zu laden.

Es spart nur das Ausrechnen der Sektorzahl und manuelle drankleben des Headers. Mit einem externen Skript geht das genauso gut oder schlecht.

Na, dann hoffe ich mal, dass sich die auf diese Weise kreierte Bootdisk problemlos mit Super-Copy oder Boot2XEX o.ä. in eine COM/XEX Datei umwandeln lässt... 😉

CharlieChaplin schrieb: Na, dann hoffe ich mal, dass sich die auf diese Weise kreierte Bootdisk problemlos mit Super-Copy oder Boot2XEX o.ä. in eine COM/XEX Datei umwandeln lässt... 😉

Immer diese Jünger des Gottes der Multidisk. 😂

Klar geht das, hat aber im Fall von NOS absolut keinen Sinn weil das nur gebootet werden kann/darf/muss (und hinterher keine Diskettenlaufwerke mehr kennt). Und der Auslöser für meine Veröffentlichung war ein Programmierer, der einen Code schreiben will, der auf dem 5200 und 8-Bit Computer laufen soll. Da hilft ihm XEX mit seinen Headern auch nichts; das muss auf dem 5200 ins ROM.